package com.zb.excel.importExcel.listener;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zb.constant.GoodsConstant;
import com.zb.constant.RedisImportDataConstant;
import com.zb.entity.*;
import com.zb.excel.GoodsExcelImport;
import com.zb.redis.RedisUtil;
import com.zb.service.*;
import com.zb.utils.RandomUtil;
import com.zb.utils.TransactionUtil;
import com.zb.utils.ZbExcelFieldUtil;
import com.zb.websocket.server.ProgressWebSocketServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Author WEN
 * @Date 2024/2/10 0010
 **/
public class GoodsExcelImportListener implements ReadListener<GoodsExcelImport> {
    private static final Logger logger = LoggerFactory.getLogger(GoodsExcelImportListener.class);
    private static int BATCH_COUNT = 100; // 每批次执行插入数据库数量
    private boolean isFirstSend; // 是否首次发送进度
    private boolean isTwoSend; // 是否二次发送进度
    private boolean isEndSend; // 是否最后一次发送进度
    private int excelTotalRowCount; // Excel总数量（此包含空行的数量）
    private int totalCount; // 导入的总数量
    // 进度uuid识别码
    private String progressUuid;
    private PlatformTransactionManager transactionManager;
    private ZjBrandService brandService;
    private ZjGoodsTypeService typeService;
    private ZjGoodsUnitService unitService;
    private ZjProductService productService;
    private ZjProductSpecService productSpecService;
    private ZjSpareService spareService;
    private ZjSpareSpecInfoService specInfoService;
    private StringBuffer message;
    private List<GoodsExcelImport> importFailt;
    private AccounLoginInfo loginInfo;
    // 校验数据重复的缓存key
    private String check_data_repeat_key = RedisImportDataConstant.EXCEL + "check-goods-data-repeat:";
    private Map<String, Object> dataRepeatMap;
    private String CACHE_IMPORT_DATA_REDIS_KEY = RedisImportDataConstant.GOODS_IMPORT;

    // 导入的批次
    private int batch_no;
    // 当前执行的数量
    private long currentExcuteCount;

    private List<ZjBrand> brandList;
    private List<ZjGoodsType> typeList;
    private List<ZjGoodsUnit> unitList;
    private Integer type; // 商品类型：1-成品，2-配件
    private List<ZjProduct> addProductList;
    private List<ZjProduct> updateProductList;
    private List<ZjProductSpec> addProductSpecList;
    private List<ZjProductSpec> updateProductSpecList;
    private List<ZjSpare> addSpareList;
    private List<ZjSpare> updateSpareList;
    private List<ZjSpareSpecInfo> addSpareSpecInfoList;
    private List<ZjSpareSpecInfo> updateSpareSpecInfoList;



    public GoodsExcelImportListener(AccounLoginInfo loginInfo, Integer type, String uuid, PlatformTransactionManager transactionManager, ZjBrandService brandService,
                                    ZjGoodsTypeService typeService, ZjGoodsUnitService unitService, ZjProductService productService, ZjProductSpecService productSpecService, ZjSpareService spareService,
                                    ZjSpareSpecInfoService specInfoService) {
        this.isFirstSend = true;
        this.isTwoSend = true;
        this.isEndSend = false;
        this.excelTotalRowCount = 0;
        this.totalCount = 0;
        this.message = new StringBuffer();
        this.importFailt = new ArrayList<>();
        this.loginInfo = loginInfo;
        this.progressUuid = uuid;
        this.check_data_repeat_key = check_data_repeat_key + loginInfo.getCustAccId() + ":" + this.progressUuid;
        this.dataRepeatMap = new HashMap<>();
        this.batch_no = 0;
        this.currentExcuteCount = 0;
        this.CACHE_IMPORT_DATA_REDIS_KEY = this.CACHE_IMPORT_DATA_REDIS_KEY + loginInfo.getCustAccId() + this.progressUuid;

        this.type = type;
        this.transactionManager = transactionManager;
        this.brandService = brandService;
        this.typeService = typeService;
        this.unitService = unitService;
        this.productService = productService;
        this.productSpecService = productSpecService;
        this.spareService = spareService;
        this.specInfoService = specInfoService;
        initData();
    }

    private void initData() {
        this.brandList = new ArrayList<>();
        this.typeList = new ArrayList<>();
        this.unitList = new ArrayList<>();
        this.addProductList = new ArrayList<>();
        this.updateProductList = new ArrayList<>();
        this.addProductSpecList = new ArrayList<>();
        this.updateProductSpecList = new ArrayList<>();
        this.addSpareList = new ArrayList<>();
        this.updateSpareList = new ArrayList<>();
        this.addSpareSpecInfoList = new ArrayList<>();
        this.updateSpareSpecInfoList = new ArrayList<>();
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        this.excelTotalRowCount = context.readSheetHolder().getApproximateTotalRowNumber();
        this.totalCount = this.excelTotalRowCount -2;
        if (this.isFirstSend) {
            this.message.append("数据正在解析中，请稍等...").append("</br>");
            ProgressWebSocketServer.send(this.progressUuid, false,  new ArrayList(), this.message.toString());
            this.isFirstSend = false;
        }
    }

    @Override
    public void invoke(GoodsExcelImport goodsExcelImport, AnalysisContext analysisContext) {
        if (this.isTwoSend) {
            this.message.append("数据解析成功，正在导入中..").append("</br>");
            ProgressWebSocketServer.send(this.progressUuid, false,  new ArrayList(), this.message.toString());
            this.isTwoSend = false;
        }
        this.currentExcuteCount++;
        analysisContext.readWorkbookHolder().setIgnoreEmptyRow(false);
        int rowNo = analysisContext.readRowHolder().getRowIndex() + 1; // Excel行号
        if (ZbExcelFieldUtil.isLineNullValue(goodsExcelImport)) {
            this.totalCount--;
            return;
        }
        // 校验空值
        if (checkEmpty(goodsExcelImport, rowNo)) {
            sendMessage();
            return;
        }
        // 校验是否重复
        if (checkDataRepeat(goodsExcelImport, rowNo)) {
            sendMessage();
            return;
        }
        Map<String, Object> mapKey = getCacheData();
        ZjBrand brand = null;
        if (null != mapKey.get("goods_brand_" + goodsExcelImport.getGoodsBrand())) {
            brand = JSON.parseObject(JSON.toJSONString(mapKey.get("goods_brand_" + goodsExcelImport.getGoodsBrand())), ZjBrand.class);
        } else {
            brand = new ZjBrand();
            brand.setId(IdWorker.getId());
            brand.setCustAccId(loginInfo.getCustAccId());
            brand.setName(goodsExcelImport.getGoodsBrand());
            brand.setCode("B" + RandomUtil.random8());
            brand.setTelephone("");
            brand.setCompany("");
            brand.setProvince("");
            brand.setCity("");
            brand.setArea("");
            brand.setTown("");
            brand.setAddress("");
            brand.setMark("");
            brand.setPublicNo("");
            brand.setDisabled(false);
            this.brandList.add(brand);
            mapKey.put("goods_brand_" + goodsExcelImport.getGoodsBrand(), brand);
        }
        ZjGoodsType type = null;
        if (null != mapKey.get("goods_type_" + goodsExcelImport.getGoodsType())) {
            type = JSON.parseObject(JSON.toJSONString(mapKey.get("goods_type_" + goodsExcelImport.getGoodsType())), ZjGoodsType.class);
        } else {
            type = new ZjGoodsType();
            type.setId(IdWorker.getId());
            type.setCustAccId(loginInfo.getCustAccId());
            type.setName(goodsExcelImport.getGoodsType());
            type.setDisabled(false);
            this.typeList.add(type);
            mapKey.put("goods_type_" + goodsExcelImport.getGoodsType(), type);
        }
        ZjGoodsUnit unit = null;
        if (null != mapKey.get("goods_unit_" + goodsExcelImport.getGoodsUnit())) {
            unit = JSON.parseObject(JSON.toJSONString(mapKey.get("goods_unit_" + goodsExcelImport.getGoodsUnit())), ZjGoodsUnit.class);
        } else {
            unit = new ZjGoodsUnit();
            unit.setId(IdWorker.getId());
            unit.setCustAccId(loginInfo.getCustAccId());
            unit.setName(goodsExcelImport.getGoodsUnit());
            unit.setDisabled(false);
            this.unitList.add(unit);
            mapKey.put("goods_unit_" + goodsExcelImport.getGoodsUnit(), unit);
        }
        if (this.type == 1) {
            getProductData(goodsExcelImport, brand, type, unit, mapKey);
            RedisUtil.setCache(this.CACHE_IMPORT_DATA_REDIS_KEY, JSON.toJSONString(mapKey));
            if (this.addProductList.size() >= BATCH_COUNT || this.updateProductList.size() >= BATCH_COUNT) {
                excuteSaveProduct();
            }
        } else {
            getSpareData(goodsExcelImport, brand, type, unit, mapKey);
            RedisUtil.setCache(this.CACHE_IMPORT_DATA_REDIS_KEY, JSON.toJSONString(mapKey));
            if (this.addSpareList.size() >= BATCH_COUNT || this.updateSpareList.size() >= BATCH_COUNT) {
                excuteSaveSpare();
            }
        }
        sendMessage();
    }

    private void getProductData(GoodsExcelImport goodsExcelImport, ZjBrand brand, ZjGoodsType type, ZjGoodsUnit unit, Map<String, Object> mapKey) {
        ZjProduct product = null;
        if (null != mapKey.get("goods_product_model_" + goodsExcelImport.getGoodsModel())) {
            product = JSON.parseObject(JSON.toJSONString(mapKey.get("goods_product_model_" + goodsExcelImport.getGoodsModel())), ZjProduct.class);
            product.setBrandId(brand.getId());
            product.setBrand(brand.getName());
            product.setCode(StringUtils.isNotBlank(goodsExcelImport.getGoodsCode())? goodsExcelImport.getGoodsCode() : product.getCode());
            product.setName(StringUtils.isNotBlank(goodsExcelImport.getGoodsName())? goodsExcelImport.getGoodsName() : product.getName());
            product.setItemNumber(StringUtils.isNotBlank(goodsExcelImport.getGoodsItemNumber())? goodsExcelImport.getGoodsItemNumber() : product.getItemNumber());
            product.setTypeId(type.getId());
            product.setType(type.getName());
            product.setUnitId(unit.getId());
            product.setUnit(unit.getName());
            this.updateProductList.add(product);
        } else {
            product = new ZjProduct();
            product.setId(IdWorker.getId());
            product.setCustAccId(loginInfo.getCustAccId());
            product.setBrandId(brand.getId());
            product.setBrand(brand.getName());
            product.setName(StringUtils.isNotBlank(goodsExcelImport.getGoodsName())? goodsExcelImport.getGoodsName() : goodsExcelImport.getGoodsModel());
            product.setModel(goodsExcelImport.getGoodsModel());
            product.setCode(StringUtils.isNotBlank(goodsExcelImport.getGoodsCode())? goodsExcelImport.getGoodsCode() : "BM" + RandomUtil.random10());
            product.setItemNumber(StringUtils.isNotBlank(goodsExcelImport.getGoodsItemNumber())? goodsExcelImport.getGoodsItemNumber() : "HH" + RandomUtil.random10());
            product.setUnitId(unit.getId());
            product.setUnit(unit.getName());
            product.setTypeId(type.getId());
            product.setType(type.getName());
            product.setSource(GoodsConstant.SOURCE_2);
            product.setEnabledRegister(false);
            product.setDeleted(false);
            product.setDisabled(false);
            product.setCreateEmpId(loginInfo.getId());
            product.setUpdateEmpId(loginInfo.getId());
            this.addProductList.add(product);
        }
        ZjProductSpec productSpec = null;
        if (null != mapKey.get("goods_product_spec_name_" + product.getId() + goodsExcelImport.getGoodsSpecName())) {
            productSpec = JSON.parseObject(JSON.toJSONString(mapKey.get("goods_product_spec_name_" + product.getId() + goodsExcelImport.getGoodsSpecName())), ZjProductSpec.class);
            productSpec.setCode(StringUtils.isNotBlank(goodsExcelImport.getGoodsSpecSku())? goodsExcelImport.getGoodsSpecSku() : productSpec.getCode());
            productSpec.setPrice(StringUtils.isNotBlank(goodsExcelImport.getPrice())? new BigDecimal(goodsExcelImport.getPrice()) : productSpec.getPrice());
            productSpec.setWarrantyDay(null != goodsExcelImport.getWarrantDay()? goodsExcelImport.getWarrantDay() : productSpec.getWarrantyDay());
            this.updateProductSpecList.add(productSpec);
        } else {
            productSpec = new ZjProductSpec();
            productSpec.setId(IdWorker.getId());
            productSpec.setCustAccId(loginInfo.getCustAccId());
            productSpec.setProductId(product.getId());
            productSpec.setName(goodsExcelImport.getGoodsSpecName());
            productSpec.setEnabled(true);
            productSpec.setImage("");
            productSpec.setPrice(StringUtils.isNotBlank(goodsExcelImport.getPrice())? new BigDecimal(goodsExcelImport.getPrice()) : new BigDecimal("0.0"));
            productSpec.setWarrantyDay(null == goodsExcelImport.getWarrantDay()? 30 : goodsExcelImport.getWarrantDay());
            productSpec.setCode(StringUtils.isNotBlank(goodsExcelImport.getGoodsSpecSku())? goodsExcelImport.getGoodsSpecSku() : "PSKU" + RandomUtil.random10());
            this.addProductSpecList.add(productSpec);
        }
        mapKey.put("goods_product_model_" + goodsExcelImport.getGoodsModel(), product);
        mapKey.put("goods_product_spec_name_" + product.getId() + goodsExcelImport.getGoodsSpecName(), productSpec);
    }

    private void getSpareData(GoodsExcelImport goodsExcelImport, ZjBrand brand, ZjGoodsType type, ZjGoodsUnit unit, Map<String, Object> mapKey) {
        ZjSpare spare = null;
        if (null != mapKey.get("goods_spare_model_" + goodsExcelImport.getGoodsModel())) {
            spare = JSON.parseObject(JSON.toJSONString(mapKey.get("goods_spare_model_" + goodsExcelImport.getGoodsModel())), ZjSpare.class);
            spare.setBrandId(brand.getId());
            spare.setBrand(brand.getName());
            spare.setCode(StringUtils.isNotBlank(goodsExcelImport.getGoodsCode())? goodsExcelImport.getGoodsCode() : spare.getCode());
            spare.setName(StringUtils.isNotBlank(goodsExcelImport.getGoodsName())? goodsExcelImport.getGoodsName() : spare.getName());
            spare.setItemNumber(StringUtils.isNotBlank(goodsExcelImport.getGoodsItemNumber())? goodsExcelImport.getGoodsItemNumber() : spare.getItemNumber());
            spare.setTypeId(type.getId());
            spare.setType(type.getName());
            spare.setUnitId(unit.getId());
            spare.setUnit(unit.getName());
            this.updateSpareList.add(spare);
        } else {
            spare = new ZjSpare();
            spare.setId(IdWorker.getId());
            spare.setCustAccId(loginInfo.getCustAccId());
            spare.setBrandId(brand.getId());
            spare.setBrand(brand.getName());
            spare.setName(StringUtils.isNotBlank(goodsExcelImport.getGoodsName())? goodsExcelImport.getGoodsName() : goodsExcelImport.getGoodsModel());
            spare.setModel(goodsExcelImport.getGoodsModel());
            spare.setCode(StringUtils.isNotBlank(goodsExcelImport.getGoodsCode())? goodsExcelImport.getGoodsCode() : "BM" + RandomUtil.random10());
            spare.setItemNumber(StringUtils.isNotBlank(goodsExcelImport.getGoodsItemNumber())? goodsExcelImport.getGoodsItemNumber() : "HH" + RandomUtil.random10());
            spare.setUnitId(unit.getId());
            spare.setUnit(unit.getName());
            spare.setTypeId(type.getId());
            spare.setType(type.getName());
            spare.setSource(GoodsConstant.SOURCE_2);
            spare.setSupplier("");
            spare.setSupplierTelephone("");
            spare.setDeleted(false);
            spare.setDisabled(false);
            spare.setCreateEmpId(loginInfo.getId());
            spare.setUpdateEmpId(loginInfo.getId());
            this.addSpareList.add(spare);
        }
        ZjSpareSpecInfo spareSpecInfo = null;
        if (null != mapKey.get("goods_spare_spec_name_" + spare.getId() + goodsExcelImport.getGoodsSpecName())) {
            spareSpecInfo = JSON.parseObject(JSON.toJSONString(mapKey.get("goods_spare_spec_name_" + spare.getId() + goodsExcelImport.getGoodsSpecName())), ZjSpareSpecInfo.class);
            spareSpecInfo.setCode(StringUtils.isNotBlank(goodsExcelImport.getGoodsSpecSku())? goodsExcelImport.getGoodsSpecSku() : spareSpecInfo.getCode());
            spareSpecInfo.setPrice(StringUtils.isNotBlank(goodsExcelImport.getPrice())? new BigDecimal(goodsExcelImport.getPrice()) : spareSpecInfo.getPrice());
            spareSpecInfo.setWarrantyDay(null != goodsExcelImport.getWarrantDay()? goodsExcelImport.getWarrantDay() : spareSpecInfo.getWarrantyDay());
            this.updateSpareSpecInfoList.add(spareSpecInfo);
        } else {
            spareSpecInfo = new ZjSpareSpecInfo();
            spareSpecInfo.setId(IdWorker.getId());
            spareSpecInfo.setCustAccId(loginInfo.getCustAccId());
            spareSpecInfo.setSpareId(spare.getId());
            spareSpecInfo.setName(goodsExcelImport.getGoodsSpecName());
            spareSpecInfo.setEnabled(true);
            spareSpecInfo.setImage("");
            spareSpecInfo.setPrice(StringUtils.isNotBlank(goodsExcelImport.getPrice())? new BigDecimal(goodsExcelImport.getPrice()) : new BigDecimal("0.0"));
            spareSpecInfo.setOverPrice(spareSpecInfo.getPrice());
            spareSpecInfo.setWarrantyDay(null == goodsExcelImport.getWarrantDay()? 30 : goodsExcelImport.getWarrantDay());
            spareSpecInfo.setCode(StringUtils.isNotBlank(goodsExcelImport.getGoodsSpecSku())? goodsExcelImport.getGoodsSpecSku() : "PSKU" + RandomUtil.random10());
            this.addSpareSpecInfoList.add(spareSpecInfo);
        }
        mapKey.put("goods_spare_model_" + goodsExcelImport.getGoodsModel(), spare);
        mapKey.put("goods_spare_spec_name_" + spare.getId() + goodsExcelImport.getGoodsSpecName(), spareSpecInfo);
    }

    /**
     * 校验必填字段是否为空
     * @param goods
     * @param rowNo
     * @return
     */
    private boolean checkEmpty(GoodsExcelImport goods, int rowNo) {
        if (StringUtils.isBlank(goods.getGoodsBrand())) {
            this.importFailt.add(goods);
            message.append("A").append(rowNo).append("单元 商品品牌不能为空").append("</br>");
            return true;
        }
        if (StringUtils.isBlank(goods.getGoodsModel())) {
            this.importFailt.add(goods);
            message.append("B").append(rowNo).append("单元 商品型号不能为空").append("</br>");
            return true;
        }
        if (StringUtils.isBlank(goods.getGoodsType())) {
            this.importFailt.add(goods);
            message.append("F").append(rowNo).append("单元 商品分类不能为空").append("</br>");
            return true;
        }
        if (StringUtils.isBlank(goods.getGoodsUnit())) {
            this.importFailt.add(goods);
            message.append("G").append(rowNo).append("单元 商品单位不能为空").append("</br>");
            return true;
        }
        if (StringUtils.isBlank(goods.getGoodsSpecName())) {
            this.importFailt.add(goods);
            message.append("H").append(rowNo).append("单元 商品规格名称不能为空").append("</br>");
            return true;
        }
        return false;
    }

    /**
     * 校验数据是否重复
     * @param goods
     * @param rowNo
     * @return
     */
    private boolean checkDataRepeat(GoodsExcelImport goods, int rowNo) {
        boolean isDataRepeat = false;
        Object byKey = RedisUtil.getByKey(check_data_repeat_key);
        dataRepeatMap = JSON.parseObject((String) byKey, HashMap.class);
        if (null == dataRepeatMap) {
            dataRepeatMap = new HashMap<>();
        }
        if (null != dataRepeatMap.get("goods_model_" + goods.getGoodsModel())) {
            message.append("B").append(rowNo).append("单元 商品型号已重复填写").append("</br>");
            isDataRepeat = true;
        } else {
            dataRepeatMap.put("goods_model_" + goods.getGoodsModel(), true);
        }
        if (StringUtils.isNotBlank(goods.getGoodsCode())) {
            if (null != dataRepeatMap.get("goods_code_" + goods.getGoodsCode())) {
                message.append("C").append(rowNo).append("单元 商品编号已重复填写").append("</br>");
                isDataRepeat = true;
            } else {
                dataRepeatMap.put("goods_code_" + goods.getGoodsCode(), true);
            }
        }
        if (StringUtils.isNotBlank(goods.getGoodsItemNumber())) {
            if (null != dataRepeatMap.get("goods_ItemNumber_" + goods.getGoodsItemNumber())) {
                message.append("E").append(rowNo).append("单元 商品货号已重复填写").append("</br>");
                isDataRepeat = true;
            } else {
                dataRepeatMap.put("goods_ItemNumber_" + goods.getGoodsItemNumber(), true);
            }
        }
        if (StringUtils.isNotBlank(goods.getGoodsSpecSku())) {
            if (null != dataRepeatMap.get("goods_spec_sku_" + goods.getGoodsSpecSku())) {
                message.append("I").append(rowNo).append("单元 商品规格SKU三已重复填写").append("</br>");
                isDataRepeat = true;
            } else {
                dataRepeatMap.put("goods_spec_sku_" + goods.getGoodsSpecSku(), true);
            }
        }
        RedisUtil.setCache(check_data_repeat_key, JSON.toJSONString(dataRepeatMap));
        if (isDataRepeat) {
            this.importFailt.add(goods);
            return true;
        }
        return false;
    }

    /**
     * 获取缓存的数据
     * @return
     */
    private Map<String, Object> getCacheData() {
        Map<String, Object> cacheData = null;
        Object byKey = RedisUtil.getByKey(this.CACHE_IMPORT_DATA_REDIS_KEY);
        if (null == byKey) {
            return new HashMap<>();
        }
        cacheData = JSON.parseObject((String) byKey, Map.class);
        return cacheData;
    }

    private void excuteSaveProduct() {
        String color = "#67C23A";
        this.batch_no++;
        this.message.append("<div style=color:").append(color).append(">解析完成，正在处理保存 [第 ").append(this.batch_no).append("批] 数据，请耐心等待...</div>");
        sendMessage();
        this.message.append("<div style=color:").append(color).append(">第 ").append(this.batch_no);
        TransactionStatus status = this.transactionManager.getTransaction(TransactionUtil.transactionDefinition());
        try {
            if (CollectionUtil.isNotEmpty(brandList)) this.brandService.saveBatch(brandList);
            if (CollectionUtil.isNotEmpty(typeList)) this.typeService.saveBatch(typeList);
            if (CollectionUtil.isNotEmpty(unitList)) this.unitService.saveBatch(unitList);
            if (CollectionUtil.isNotEmpty(addProductList)) this.productService.saveBatch(addProductList);
            if (CollectionUtil.isNotEmpty(updateProductList)) this.productService.updateBatchById(updateProductList);
            if (CollectionUtil.isNotEmpty(addProductSpecList)) this.productSpecService.saveBatch(addProductSpecList);
            if (CollectionUtil.isNotEmpty(updateProductSpecList)) this.productSpecService.updateBatchById(updateProductSpecList);
            this.transactionManager.commit(status);
            this.message.append(" 批导入成功</div>");
        }catch (Exception e) {
            color = "#F56C6C";
            logger.error("成品第 {} 批导入失败，失败原因：{}", this.batch_no, e.getMessage());
            this.message.append(" 导入失败！原因：").append(e.getMessage()).append("</div>");
            this.transactionManager.rollback(status);
        }
        initData();
    }
    private void excuteSaveSpare() {
        String color = "#67C23A";
        this.batch_no++;
        this.message.append("<div style=color:").append(color).append(">解析完成，正在处理保存 [第 ").append(this.batch_no).append("批] 数据，请耐心等待...</div>");
        sendMessage();
        this.message.append("<div style=color:").append(color).append(">第 ").append(this.batch_no);
        TransactionStatus status = this.transactionManager.getTransaction(TransactionUtil.transactionDefinition());
        try {
            if (CollectionUtil.isNotEmpty(brandList)) this.brandService.saveBatch(brandList);
            if (CollectionUtil.isNotEmpty(typeList)) this.typeService.saveBatch(typeList);
            if (CollectionUtil.isNotEmpty(unitList)) this.unitService.saveBatch(unitList);
            if (CollectionUtil.isNotEmpty(addSpareList)) this.spareService.saveBatch(addSpareList);
            if (CollectionUtil.isNotEmpty(updateSpareList)) this.spareService.updateBatchById(updateSpareList);
            if (CollectionUtil.isNotEmpty(addSpareSpecInfoList)) this.specInfoService.saveBatch(addSpareSpecInfoList);
            if (CollectionUtil.isNotEmpty(updateSpareSpecInfoList)) this.specInfoService.updateBatchById(updateSpareSpecInfoList);
            this.transactionManager.commit(status);
            this.message.append(" 批导入成功</div>");
        }catch (Exception e) {
            e.printStackTrace();
            color = "#F56C6C";
            logger.error("配件第 {} 批导入失败，失败原因：{}", this.batch_no, e.getMessage());
            this.message.append(" 导入失败！原因：").append(e.getMessage()).append("</div>");
            this.transactionManager.rollback(status);
        }
        initData();
    }


    // 所有数据解析完执行
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        RedisUtil.clearCache(check_data_repeat_key);
        if (this.type == 1) {
            if (CollectionUtil.isNotEmpty(addProductList) || CollectionUtil.isNotEmpty(updateProductList)) {
                excuteSaveProduct();
            }
            if (!this.isEndSend) {
                ProgressWebSocketServer.send(this.progressUuid, true, 100, this.totalCount, this.importFailt, this.message.toString());
                this.isEndSend = true;
            }
            return;
        }
        if (this.type == 2) {
            if (CollectionUtil.isNotEmpty(addSpareList) || CollectionUtil.isNotEmpty(updateSpareList)) {
                excuteSaveSpare();
            }
            if (!this.isEndSend) {
                ProgressWebSocketServer.send(this.progressUuid, true, 100, this.totalCount, this.importFailt, this.message.toString());
                this.isEndSend = true;
            }
        }
    }

    /**
     * 发送进度消息
     */
    private void sendMessage() {
        if (this.type == 1) {
            ProgressWebSocketServer.send(this.progressUuid, false, (1.0 * this.currentExcuteCount / this.excelTotalRowCount *100), this.importFailt, this.message.toString());
        } else {
            ProgressWebSocketServer.send(this.progressUuid, false, (1.0 * this.currentExcuteCount / this.excelTotalRowCount *100), this.importFailt, this.message.toString());
        }
    }


}
